# -*- coding: utf-8 -*-
# @Time    : 2024/9/30 10:56
# @Author  : 荒
# @FileName: file.py
# @Software: PyCharm

from django.shortcuts import render,HttpResponse
from web.forms.file import FolderModelForm,FileModelForm
from django.http import JsonResponse
from web import models
import json
from django.forms import model_to_dict
from django.views.decorators.csrf import csrf_exempt
from utils.tencent.cos import delete_file_list,delete_file,credential
from django.urls import reverse
from django.utils.encoding import escape_uri_path  # 用于解决中文命名文件乱码问题

def file(request,project_id):
    """ 文件列表 & 添加文件夹 """

    parent_object = None
    folder_id = request.GET.get('folder', "")
    if folder_id.isdecimal():
        parent_object = models.FileRepository.objects.filter(id=int(folder_id), file_type=2,
                                                             project=request.tracer.project).first()
    # GET查看页面
    if request.method == "GET":

        breadcrumb_list = []
        parent = parent_object
        while parent:
            # breadcrumb_list.insert(0,{'id':parent.id,'name':parent.name})
            breadcrumb_list.insert(0,model_to_dict(parent,['id','name']))
            parent = parent.parent

        # 当前目录下所有的文件 & 文件夹获取到即可
        queryset = models.FileRepository.objects.filter(project=request.tracer.project)
        if parent_object:
            # 进入了某目录
            file_object_list = queryset.filter(parent=parent_object).order_by('-file_type')
        else:
            # 根目录
            file_object_list = queryset.filter(parent__isnull=True).order_by('-file_type')
        form = FolderModelForm(request,parent_object)
        context = {
            'form': form,
            'file_object_list':file_object_list,
            'breadcrumb_list': breadcrumb_list,
            'folder_object': parent_object
        }
        return render(request,'file.html',context)


    # POST 添加文件夹 & 文件夹的修改
    fid = request.POST.get('fid','')
    edit_object = None
    if fid.isdecimal():
        edit_object = models.FileRepository.objects.filter(id=int(fid),file_type=2,
                                                           project=request.tracer.project).first()
    if edit_object:
        form = FolderModelForm(request, parent_object, data=request.POST,instance=edit_object)
    else:
        form = FolderModelForm(request,parent_object,data=request.POST)

    if form.is_valid():
        form.instance.project = request.tracer.project
        form.instance.file_type = 2
        form.instance.update_user = request.tracer.user
        form.instance.parent = parent_object

        form.save()
        return JsonResponse({'status':True})

    return JsonResponse({'status':False,'error':form.errors})

# http://127.0.0.1:8000/manage/1/file/delete/?fid=1
def file_delete(request,project_id):
    """ 删除文件夹 """
    print(request.get_full_path())
    fid = request.GET.get('fid')
    print(fid)
    # 删除数据库中的 文件 & 文件夹 （级联删除）
    delete_object = models.FileRepository.objects.filter(id=fid,project=request.tracer.project).first()
    if delete_object.file_type == 1:
        # 删除文件 （数据库文件删除，cos文件删除，项目已使用空间容量还回去）
        request.tracer.project.use_space -= delete_object.file_size
        request.tracer.project.save()

        # cos中删除文件
        delete_file(request.tracer.project.bucket,request.tracer.project.region,delete_object,delete_object.key)

        # 在数据库中删除当前文件
        delete_object.delete()
    else:
        # 删除文件夹（找到文件夹下所有的文件->数据库文件删除、cos文件删除，项目已使用空间容量还回去）
        # 找他下面的 文件和文件夹

        total_size = 0
        key_list = []

        folder_list = [delete_object,]
        for folder in folder_list:
            child_list = models.FileRepository.objects.filter(project=request.tracer.project,parent=folder).order_by('-file_type')
            for child in child_list:
                if child.file_type == 2:
                    folder_list.append(child)
                else:
                    # 文件大小汇总
                    total_size += child.file_size

                    # 删除文件
                    key_list.append({"Key":child.key})

        # cos 批量删除文件
        if key_list:
            delete_file_list(request.tracer.project.bucket,request.tracer.project.region,key_list)

        if total_size:
            request.tracer.project.use_space -= total_size
            request.tracer.project.save()
        # 在数据库中删除当前文件夹
        delete_object.delete()
    return JsonResponse({'status':True})

@csrf_exempt # 免除csrf检验
def cos_credential(request,project_id):
    """ 获取从事上传的临时凭证 """
    per_file_limit = request.tracer.price_policy.per_file_size * 1024 * 1024
    total_file_limit = request.tracer.price_policy.project_space * 1024 * 1024 * 1024

    total_space = 0
    file_list = json.loads(request.body.decode('utf-8'))
    for item in file_list:
        # 文件的字节大小  item['size'] = B
        # 单文件限制的大小 M
        # 超出限制
        if item['size'] > per_file_limit:
            msg = "单文件超出限制(最大{}M),文件:{}，请升级套餐".format(request.tracer.price_policy.per_file_size,item['name'])
            return JsonResponse({'status':False,'error':msg})
        total_space += item['size']
    # 总容量限制
    #   request.tracer.price_policy.project_space 项目允许的空间
    #  request.tracer.project.use_space  项目已使用的空间
    if request.tracer.project.use_space + total_space > total_file_limit:
        return JsonResponse({'status': False, 'error': "容量超过限制，请升级套餐"})


    data_dict = credential(request.tracer.project.bucket,request.tracer.project.region)
    return JsonResponse({'status': True,'data': data_dict})


@csrf_exempt # 免除csrf检验
def file_post(request,project_id):
    """ 已上传成功的文件写入到数据库 """
    """
    name: fileName,
    key: key,
    file_size: fileSize,
    parent: CURRENT_FOLDER_ID,
    etag: data.ETag,
    file_path: data.Location
    """
    # 根据key再去cos获取文件Etal和"bd4e6b860b2f5c9ffdc4a3120f61dde0"

    # 把获取到的数据写入到数据库即可
    form = FileModelForm(request,data=request.POST)
    if form.is_valid():
        # 通过ModelForm.save存储到数据库中的数据返回的isntance对象，无法通过get_xx_display获取choice的中文
        # form.instance.file_type = 1
        # form.update_user = request.tracer.user
        # instance = form.save() # 添加成功之后，获取到新添加的那个对象（instance.id,instance.name,instance.file_type,instace.get_file_type_display()

        # 校验通过：数据写入到数据库
        data_dict = form.cleaned_data
        data_dict.pop('etag')
        print(data_dict)
        data_dict.update({'project':request.tracer.project,'file_type':1,'update_user':request.tracer.user})
        instance = models.FileRepository.objects.create(**data_dict)

        # 项目的已使用空间：更新（data_dict['file_size']）
        request.tracer.project.use_space += data_dict['file_size']
        request.tracer.project.save()

        result = {
            'id': instance.id,
            'name': instance.name,
            'file_size': instance.file_size,
            'username': instance.update_user.username,
            'datetime': instance.update_datetime.strftime('%Y年%m月%d日 %H:%M'),
            'download_url': reverse('file_download',kwargs={'project_id':project_id,'file_id':instance.id}),
            # 'file_type': instance.get_file_type_display()
        }
        return JsonResponse({'status':True,'data':result})

    return JsonResponse({'status':False,'data':'文件错误'})

def file_download(request,project_id,file_id):
    """ 下载文件 """

    import requests

    file_object = models.FileRepository.objects.filter(id=file_id,project_id=project_id).first()
    res = requests.get(file_object.file_path)
    data = res.content

    response = HttpResponse(data)
    # 设置响应头
    response['Content-Disposition'] = "attachment; filename={};".format(escape_uri_path(file_object.name))
    print(response['Content-Disposition'])
    return response